#ifndef __UDP_SERVER_HPP__
#define __UDP_SERVER_HPP__

#include <iostream>
#include <string>
#include <memory>
#include <cstring>
#include <cerrno>
#include <strings.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "Log.hpp"
#include "Common.hpp"

using namespace LogModule;

const static  std::string fault_ip = "127.0.0.1";
const static  uint16_t fault_port = 8080;
class UDPServer
{
public:
    UDPServer(std::string ip = fault_ip, uint16_t port = fault_port)
        : _ip(ip), _port(port), _isrunning(false), _sockfd(-1)
    {
    }
    void InitServer()
    {
        _sockfd = socket(AF_INET, SOCK_DGRAM, 0); //这是创建好了一个网络上的文件
        if (_sockfd < 0)
        {
            LOG(LogLevel::FATAL) << "socket create false";
            Die(USAGE_ERR);
        }
        LOG(LogLevel::INFO) << "socket success, sockfd is : " << _sockfd;
        struct sockaddr_in local;
        bzero(&local, sizeof(local)); // 最好是先清零再去给它赋值 用memset也可以
        local.sin_family = AF_INET;
        local.sin_port = ::htons(_port); // 因为字节序的问题 ，最好是要给转换成网络的大端
        local.sin_addr.s_addr = inet_addr(_ip.c_str());


        //要绑定网络上的信息  你要知道是谁传的 ip + port
        int n = bind(_sockfd, CONV(&local), sizeof(local));
        if (n < 0)
        {
            LOG(LogLevel::FATAL) << "bind: " << strerror(errno);
            Die(BIND_ERR);
        }
        LOG(LogLevel::INFO) << "bind success";
    }
    void Start()
    {
        _isrunning = true;
        while(true)
        {
            //要接受客户端的信息
            // ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
            //                   struct sockaddr *src_addr,  *addrlen);

            char inbuffer[1024];
            struct sockaddr_in peer;
           
            socklen_t len = sizeof(peer) ;
            ssize_t n = recvfrom ( _sockfd,inbuffer,sizeof(inbuffer)-1,0,CONV(&peer),&len);

            if(n>0)
            {
                uint16_t clientport = ::ntohs(peer.sin_port);
                std::string clientip = ::inet_ntoa(peer.sin_addr);
                inbuffer[n] = 0;

                std::string clientinfo = clientip + ":" + std::to_string(clientport) + "#" + inbuffer;
                LOG(LogLevel::DEBUG) << clientinfo;
                //接受消息后 还有给客户端发送数据
                std::string echo_string = "echo#" ; 
                echo_string += inbuffer;
                
                ::sendto(_sockfd,echo_string.c_str(),echo_string.size(),0,CONV(&peer),len);

                





            }


        }

    }
    ~UDPServer()
    {
    }

private:
    int _sockfd; // 建立的网络文件描述符
    std::string _ip;
    uint16_t _port;
    bool _isrunning;
};

#endif